﻿using System;
using System.Collections.Generic;
using System.Text;
using OpenTK;
using OpenTK.Graphics;
using OpenTK.Graphics.OpenGL;
using Xeno.Core;
using Xeno.Physics;

namespace Xeno.Module
{
    public class XenoMod_Camera : XenoModule
    {
        public Matrix4 Projection { get; set; }
        public float FieldOfView { get; set; }
        public float ViewWidth { get; set; }
        public float ViewHeight { get; set; }
        public float NearZ { get; set; }
        public float FarZ { get; set; }

        public XenoMod_Camera()
        {

            ResetCamera();

        }

        public void ResetCamera()
        {

            FieldOfView = 50f;
            Projection = Matrix4.Identity;
            ViewWidth = XenoCore.DisplayWidth;
            ViewHeight = XenoCore.DisplayHeight;
            NearZ = 0.3f;
            FarZ = 200.0f;
            InvertWorld = true;
            UpdateMatrices();

        }
        public Vector3 Unproject(Vector3 screenPos)
        {
           
            screenPos.Y = XenoCore.DisplayHeight - screenPos.Y;
            double[] mod = mta(Attached.WorldMatrix);
            double[] proj = mta(Projection);
            int[] view = new int[4];
            OpenTK.Graphics.OpenGL.GL.GetInteger(OpenTK.Graphics.OpenGL.GetPName.Viewport,view);
            Vector3 ret = Vector3.Zero;
            Glu.UnProject(screenPos, mod, proj, view, out ret);
            return ret;
        }
        public Xeno.Physics.CastHit Pick(float mx, float my)
        {
            if (XenoPhysicsManager.Instance == null)
            {
                return null;
            }
            Vector3 from = Unproject(new Vector3(mx, my, 0));
            Vector3 to = Unproject(new Vector3(mx, my, 1));
            Vector3 dir = to - from;
          
            to.Normalize();

            return Physics.XenoPhysicsManager.Instance.Raycast(from, to, dir.Length);
        }
        private double[] mta(Matrix4 mat)
        {
            double[] ret = new double[16];
            ret[0] = mat.M11;
            ret[1] = mat.M12;
            ret[2] = mat.M13;
            ret[3] = mat.M14;
            ret[4] = mat.M21;
            ret[5] = mat.M22;
            ret[6] = mat.M23;
            ret[7] = mat.M24;
            ret[8] = mat.M31;
            ret[9] = mat.M32;
            ret[10] = mat.M33;
            ret[11] = mat.M34;
            ret[12] = mat.M41;
            ret[13] = mat.M42;
            ret[14] = mat.M43;
            ret[15] = mat.M44;
            return ret;
        }
        public float Deg2Rad(float ang)
        {
            return ang / 57.29578f;
        }
        public float Rad2Deg(float val)
        {
            return val * 57.29578f;
        }

        public void UpdateMatrices()
        {
            float fov = Deg2Rad(FieldOfView);
            ViewWidth = XenoCore.DisplayWidth;
            ViewHeight = XenoCore.DisplayHeight;
          Projection = Matrix4.Perspective(fov, ViewWidth / ViewHeight, NearZ, FarZ);

        }

    }
}
